/*
 * FreeModbus Libary: BARE Port
 * Copyright (C) 2006 Christian Walter <wolti@sil.at>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * File: $Id$
 */

/* ----------------------- Platform includes --------------------------------*/
#include "port.h"

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"

/* ----------------------- static functions ---------------------------------*/
static void prvvTIMERExpiredISR( void );

/* ----------------------- Start implementation -----------------------------*/

// 定时器初始化，50us的定时器，MODBUS RTU模式下，通信时规定发完一组命令必须间隔3.5字符再发送下一组命令
// 这3.5字符主要作用是告诉其他设备这次命令(数据)已结束
BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;  

    MODBUS_TIM_CLK_CMD(MODBUS_TIM_CLK, ENABLE); 
    
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 50*usTim1Timerout50us - 1;  	// 下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在0x0000和0xFFFF之间。
    TIM_TimeBaseStructure.TIM_Prescaler = 36-1;					    // 预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;		    // 时钟分割
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	    // TIM向上计数模式
    TIM_TimeBaseInit(MODBUS_TIM, &TIM_TimeBaseStructure);
    
    // 中断优先级NVIC设置  
    //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
    NVIC_InitStructure.NVIC_IRQChannel = MODBUS_TIM_IRQ ;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
    NVIC_Init(&NVIC_InitStructure);   
    
    TIM_ClearITPendingBit(MODBUS_TIM, TIM_IT_Update);   // 清除溢出中断标志位  
    TIM_ITConfig(MODBUS_TIM, TIM_IT_Update, DISABLE);   // 定时器溢出中断关闭  
    TIM_Cmd(MODBUS_TIM, DISABLE);                       // 失能定时器    
    
    return TRUE;
}


// 定时器使能
inline void vMBPortTimersEnable(  )
{
    /* Enable the timer with the timeout passed to xMBPortTimersInit( ) */
    
    TIM_ClearITPendingBit(MODBUS_TIM, TIM_IT_Update);   // 清除中断标志位
    TIM_ITConfig(MODBUS_TIM, TIM_IT_Update, ENABLE);    // 使能中断
    TIM_SetCounter(MODBUS_TIM, 0x0000);                 // 设置定时器的初值    
    TIM_Cmd(MODBUS_TIM, ENABLE);                        // 使能定时器
}


// 定时器禁止使能
inline void vMBPortTimersDisable(  )
{
    /* Disable any pending timers. */

    TIM_ClearITPendingBit(MODBUS_TIM, TIM_IT_Update);   // 清除中断标志位
    TIM_ITConfig(MODBUS_TIM, TIM_IT_Update, DISABLE);   // 禁止中断
    TIM_SetCounter(MODBUS_TIM, 0x0000);                 // 设置定时器的初值 
    TIM_Cmd(MODBUS_TIM, DISABLE);                       // 失能定时器
}


/* Create an ISR which is called whenever the timer has expired. This function
 * must then call pxMBPortCBTimerExpired( ) to notify the protocol stack that
 * the timer has expired.
 */
static void prvvTIMERExpiredISR( void )
{
    ( void )pxMBPortCBTimerExpired(  );
}


// 定时器的中断处理函数
void MODBUS_TIM_IRQHandler(void)
{
	if (TIM_GetITStatus(MODBUS_TIM, TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(MODBUS_TIM, TIM_IT_Update);		
		prvvTIMERExpiredISR();
	}		
}